# from django.shortcuts import render

from django.http import JsonResponse  # 返回json数据
from django.views import View  # 类视图
from rest_framework_jwt.settings import api_settings
from .models import SysUser
from .serializer import SysUserSerializer
from role.models import SysRole, SysUserRole
from menu.models import SysMenu
from menu.serializer import SysMenuSerializer
import json
from datetime import datetime
import os
import python_django.settings as settings
from django.core.paginator import Paginator
from io import BytesIO
import base64
import uuid
from utils.captcha import CaptchaTool
from django.core.cache import cache
from django.utils.decorators import method_decorator
from django.views.decorators.csrf import csrf_exempt
from rest_framework_jwt.utils import jwt_payload_handler, jwt_encode_handler
import logging

logger = logging.getLogger("user_action")
error = logging.getLogger("error")

logger = logging.getLogger("django.request")
logger.info("这是一条普通的测试日志")
@method_decorator(csrf_exempt, name="dispatch")
class LoginView(View):
    """登录接口（支持验证码）"""

    def post(self, request):
        try:
            # 解析JSON请求体
            try:
                data = request.body.decode("utf-8")
                data = json.loads(data)
                username = data.get("username")
                # 记录登录尝试日志
                logger.info(f"登录尝试 - 用户名：{username}，IP：{request.META.get('REMOTE_ADDR')}")
                password = data.get("password")
                captchaKey = data.get("captchaKey")
                code = data.get("code")
                
                # 接受type参数，如果apifox请求就传入这个参数，代表我们现在在测试
                type = data.get("type")
                
            except json.JSONDecodeError:
                return JsonResponse(
                    {"code": 400, "message": "请求格式错误，请使用JSON格式"}
                )
            # 在这里加一个逻辑，如果是apifox请求的，就不用填验证码进来了
            if type == "apifox":
                pass
            else:
                # 如果type不传或者不为apiffox，就验证必填字段与校验验证码
                if not all([username, password, captchaKey, code]):
                    return JsonResponse(
                        {
                            "code": 400,
                            "message": "缺少必填参数：username, password, captchakey, code",
                        }
                    )

                # 验证验证码
                if not CaptchaTool().verify_captcha(captchaKey, code):
                    return JsonResponse({"code": 400, "message": "验证码错误或已过期"})

            # 验证用户名和密码
            try:
                user = SysUser.objects.get(username=username, password=password)
                logger.info(f"登录成功 - 用户名:{username}，用户ID：{user.id}")

                # 生成JWT token
                payload = jwt_payload_handler(user)
                token = jwt_encode_handler(payload)

                # 查询用户角色信息
                rolelist = SysRole.objects.filter(
                    sysuserrole__user_id=user.id
                ).distinct()
                # roles = ",".join([role.name for role in rolelist])
                roles = ""
                for role in rolelist:
                    roles += role.name + ","
                roles = roles[0:-1]

                # 获取菜单信息
                menuset = set()
                menulist = SysMenu.objects.filter(
                    sysrolemenu__role_id__in=rolelist.values("id")
                ).distinct()

                for row in menulist:
                    menuset.add(row)

                # 构建树形菜单
                menulist = list(menuset)
                sortedmenulist = sorted(menulist)
                sysMenuList = self.bulid_menu_tree(sortedmenulist)

                serializerMenuList = []
                for sysMenu in sysMenuList:
                    serializerMenuList.append(SysMenuSerializer(sysMenu).data)

                return JsonResponse(
                    {
                        "code": 200,
                        "token": token,
                        "user": SysUserSerializer(user).data,
                        "message": "登录成功",
                        "menuList": serializerMenuList,
                        "roles": roles,
                    }
                )

            except SysUser.DoesNotExist:
                logger.warning(f"登录失败 - 用户名：{username}，原因：用户名或密码错误")
                return JsonResponse({"code": 400, "message": "用户名或密码错误"})

        except Exception as e:
            logger.error(f"登录异常 - 用户名：{username}，错误信息：{str(e)}， ", exc_info=True) #exc_info=True打印堆栈信息
            return JsonResponse({"code": 500, "message": "系统错误，请稍后重试"})

    def bulid_menu_tree(self, sysMenuList):
        # 最终的树形菜单列表，也是返回给前端的
        resultmenulist = []

        menu_dict = {
            menu.id: menu for menu in sysMenuList
        }  # 创建字典快速寻找父节点, key=menu_id, value=menu对象
        for menu in sysMenuList:
            if menu.parent_id == 0:
                resultmenulist.append(menu)  # 父节点
            else:
                parent = menu_dict.get(menu.parent_id)
                if not hasattr(parent, "children"):
                    parent.children = []
                parent.children.append(
                    menu
                )  # 如果放循环里面，children会重复添加；子节点

        return resultmenulist


class TestView(View):
    def get(self, request):
        # userlist_obj = SysUser.objects.filter(username="xiaoxu") # == "selct * from sys_user where username = 'xiaoxi'"
        # userlist_obj = SysUser.objects.all() # == "selct * from sys_user"
        token = request.META.get("HTTP_AUTHORIZATION")  # 获取请求头中的token
        print("token:", token)
        if token:
            userlist_obj = SysUser.objects.all().values()  # QuerySet对象转存为字典
            userlist = list(userlist_obj)  # QuerySet对象转列表
            return JsonResponse(
                {"code": 200, "message": "用户模块get请求成功", "data": userlist}
            )
        else:
            return JsonResponse({"code": 401, "message": "未登录，请先登录"})


# jwt测试
class JwtTestView(View):
    def get(self, request):
        user = SysUser.objects.get(username="xiaoxu", password="0331")
        jwt_payload_handler = api_settings.JWT_PAYLOAD_HANDLER  # 载荷
        jwt_encode_handler = api_settings.JWT_ENCODE_HANDLER  # 加密
        # 1.将用户对象传入载荷，获取该对象的属性值
        payload = jwt_payload_handler(user)
        # 2.将载荷进行加密，生成token/将属性编码成JWT格式的字符串
        token = jwt_encode_handler(payload)

        return JsonResponse(
            {"code": 200, "message": "用户模块get请求成功", "token": token}
        )


# 添加修改用户
class SaveView(View):
    def post(self, request):
        data = json.loads(request.body.decode("utf-8"))
        print(data)
        if data["id"] == -1:  # 新增
            obj_sysUser = SysUser(
                username=data["username"],
                password=data["password"],
                email=data["email"],
                phonenumber=data["phonenumber"],
                status=data["status"],
                remark=data["remark"],
            )
            obj_sysUser.create_time = datetime.now().date
            obj_sysUser.avatar = "default.jpg"
            obj_sysUser.password = "123456"
            obj_sysUser.save()
        else:  # 修改
            obj_sysUser = SysUser(
                id=data["id"],
                username=data["username"],
                password=data["password"],
                avatar=data["avatar"],
                email=data["email"],
                phonenumber=data["phonenumber"],
                create_time=data["create_time"],
                update_time=data["update_time"],
                login_time=data["login_time"],
                status=data["status"],
                remark=data["remark"],
            )
            obj_sysUser.update_time = datetime.now().date
            obj_sysUser.save()

        return JsonResponse({"code": 200, "message": "保存成功"})


# 根据ID获取用户信息和删除用户
class ActionView(View):
    def get(self, request):
        """
        根据ID获取用户信息
        """
        id = request.GET.get("id")
        user_object = SysUser.objects.get(id=id)
        return JsonResponse(
            {
                "code": 200,
                "message": "操作成功",
                "user": SysUserSerializer(user_object).data,
            }
        )

    def delete(self, request):
        """
        删除用户
        """
        idList = json.loads(request.body.decode("utf-8"))
        SysUserRole.objects.filter(user_id__in=idList).delete()
        SysUser.objects.filter(id__in=idList).delete()
        return JsonResponse({"code": 200, "message": "删除成功"})


# 检查用户名是否存在
class CheckView(View):
    def post(self, request):
        """
        检查用户名是否存在
        """
        data = json.loads(request.body.decode("utf-8"))
        username = data["username"]
        print(username)
        if SysUser.objects.filter(username=username).exists():
            return JsonResponse({"code": 500, "message": "用户名已存在"})
        else:
            return JsonResponse({"code": 200, "message": "用户名不存在"})


# 修改密码
class PwdView(View):
    def post(self, request):
        data = json.loads(request.body.decode("utf-8"))  # 获取请求体,转为字典
        id = data["id"]
        oldPassword = data["oldPassword"]
        newPassword = data["newPassword"]
        obj_user = SysUser.objects.get(id=id)
        if obj_user.password == oldPassword:
            obj_user.password = newPassword
            obj_user.update_time = datetime.now().date
            obj_user.save()
            return JsonResponse({"code": 200, "message": "密码修改成功"})
        else:
            return JsonResponse({"code": 400, "message": "密码修改失败"})


# 上传头像
class ImageView(View):
    def post(self, request):
        file = request.FILES.get("avatar")  # 获取上传的文件
        print("file:", file)
        if file:
            file_name = file.name
            suffiName = file_name[file_name.rfind(".") :]  # 获取文件后缀名
            new_file_name = (
                datetime.now().strftime("%Y%m%d%H%M%S") + suffiName
            )  # 生成新的文件名
            file_path = os.path.join(
                settings.UPLOAD_USER_AVATAR_PATH, new_file_name
            )  # 生成文件路径
            with open(file_path, "wb") as f:
                for chunk in file.chunks():  # 将文件分块写入文件
                    f.write(chunk)
            return JsonResponse(
                {"code": 200, "message": "文件上传成功", "title": new_file_name}
            )
        else:
            return JsonResponse({"code": 400, "message": "文件上传失败"})


# 修改头像
class AvatarView(View):
    def post(self, request):
        data = json.loads(request.body.decode("utf-8"))
        id = data["id"]
        avatar = data["avatar"]
        obj_user = SysUser.objects.get(id=id)
        obj_user.avatar = avatar
        obj_user.save()
        return JsonResponse({"code": 200, "message": "头像修改成功"})


# 分页查询和搜索
class searchView(View):
    def post(self, request):
        data = json.loads(request.body.decode("utf-8"))
        pageNum = data["pageNum"]
        pageSize = data["pageSize"]
        query = data["query"]  # 查询参数
        userpageList = Paginator(
            SysUser.objects.filter(username__icontains=query), pageSize
        ).page(pageNum)  # 分页,每页显示pageSize条数据
        print(userpageList)
        object_user = userpageList.object_list.values()  # 将QuerySet对象转字典
        users = list(object_user)
        for user in users:
            userID = user["id"]
            roleLsit = SysRole.objects.raw(
                "SELECT id,NAME FROM sys_role WHERE id IN (SELECT role_id FROM sys_user_role WHERE user_id="
                + str(userID)
                + ")"
            )
            roleListDict = []
            for role in roleLsit:
                roleDict = {}
                roleDict["id"] = role.id
                roleDict["name"] = role.name
                roleListDict.append(roleDict)
            user["roleList"] = roleListDict  # 将角色列表添加到用户字典中 ?
        total = SysUser.objects.filter(username__icontains=query).count()
        return JsonResponse(
            {"code": 200, "message": "查询成功", "userList": users, "total": total}
        )


# 修改密码
class PasswordView(View):
    def get(self, request):
        id = request.GET.get("id")
        user_object = SysUser.objects.get(id=id)
        user_object.password = "123456"
        user_object.update_time = datetime.now().date
        user_object.save()
        return JsonResponse({"code": 200, "message": "密码修改成功"})


# 用户状态修改
class StatusView(View):
    def post(self, request):
        data = json.loads(request.body.decode("utf-8"))
        id = data["id"]
        status = data["status"]
        user_object = SysUser.objects.get(id=id)
        user_object.status = status
        user_object.save()
        return JsonResponse({"code": 200, "message": "用户状态修改成功"})


# 分配角色
class GrantRole(View):
    """
    用户角色授权？
    """

    def post(self, request):
        data = json.loads(request.body.decode("utf-8"))
        user_id = data["id"]
        roleIdlist = data["roleIds"]  # 角色id列表
        print(user_id, roleIdlist)
        SysUserRole.objects.filter(
            user_id=user_id
        ).delete()  # 删除用户角色关联表中的指定数据
        for roleId in roleIdlist:
            userRole = SysUserRole(user_id=user_id, role_id=roleId)
            userRole.save()
        return JsonResponse({"code": 200, "message": "分配角色成功"})


class GetCaptchaView(View):
    def get(self, request):
        """获取验证码"""
        tool = CaptchaTool()

        # 1) 生成验证码文本并缓存 5 分钟
        captcha_text = tool.generate_captcha_text()
        key = str(uuid.uuid4())
        cache.set(f"captcha:{key}", captcha_text, 300)  # 加个前缀更安全

        # 2) 生成验证码图片（PIL.Image）
        image = tool.generate_captcha_image(captcha_text)

        # 3) 图片转字节流 -> Base64 字符串（注意是 b64encode）
        buffer = BytesIO()
        image.save(buffer, format="PNG")
        image_bytes = buffer.getvalue()
        image_base64 = base64.b64encode(image_bytes).decode("utf-8")

        return JsonResponse(
            {
                "code": 200,
                "captcha_key": key,
                "image": image_base64,  # 或者只返回 image_base64 字符串
            }
        )


class SearchUserRoleView(View):
    def get(self, request):
        """
        根据用户ID查询已分配的角色，返回角色列表字典
        """
        data = request.GET
        # user_id = data["userId"] # 用户ID，前端传过来
        # 健壮性写法
        user_id = data.get("userId")
        if not user_id:
            return JsonResponse({"code": 400, "message": "需要传入用户ID"}) # 先判断是否传入用户ID，没有就返回错误
        roles = SysRole.objects.filter(sysuserrole__user_id=user_id).distinct()
        roles_list = []
        for role in roles:
            role_dict = {}
            role_dict["id"] = role.id
            role_dict["name"] = role.name
            roles_list.append(role_dict)

        return JsonResponse({"code": 200, "message": "查询成功", "roles": roles_list})

class SearchAllView(View):
    def get(self, request):
        users = SysUser.objects.all()
        userlist = []
        for user in users:
            user_dict = {}
            username = user.username
            user_dict["username"] = username
            userID = user.id
            roles = SysRole.objects.filter(sysuserrole__user_id=userID)
            roles_list = []
            for role in roles: #只要用户列表里的ID和name
                role_dict = {}
                role_dict["id"] = role.id
                role_dict["name"] = role.name
                roles_list.append(role_dict)
            user_dict["roleList"] = roles_list
            userlist.append(user_dict)
        return JsonResponse({"code": 200, "message": "查询成功", "userList": userlist})
            
                
     
      